/* Transform cfg to vcg.

   Copyright (C) 2009, 2010 Mingjie Xing, mingjie.xing@gmail.com. 

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include <unistd.h>
#include <error.h>
#include <obstack.h>

#include <argp.h>

#include "tree2mooi.h"


/* Concatenate an arbitrary number of strings.  You must pass NULL as
   the last argument of this function, to terminate the list of
   strings.  Allocates memory using xmalloc.  */

extern char *concat (const char *, ...);


void
cfg_to_mooigraph (void)
{
  struct control_flow_graph *cfg;
  struct basic_block *bb;
  struct edge *e;

  char *str_a, *str_b;

  fprintf (fout, "void graph (void) {\n");
  fprintf (fout, "  settings (void) { folded=\"yes\"; }\n");

  /* top graph */

  for (current_function = first_function; current_function != NULL;
       current_function = current_function->next)
    {
      cfg = current_function->cfg;
      fprintf (fout, "subgraph(\"%s\") {\n", current_function->name);
      fprintf (fout, " settings (void) { folded=\"yes\"; }\n");
      fprintf (fout, " node(\"%s.summary\") { label=\"%s\"; }\n",
	       current_function->name, current_function->name);
      fprintf (fout, " edge(\"%s.summary\",\"%s.ENTRY\");\n",
	       current_function->name, current_function->name);

      for (bb = cfg->bb; bb != NULL; bb = bb->next)
	{
	  /* bb graph */
	  str_a = concat (current_function->name, ".", bb->name, NULL);
	  fprintf (fout, "subgraph (\"%s_%s\") {\n", current_function->name,
		   bb->name);
	  fprintf (fout,
		   "settings (void) { folded=\"yes\"; label=\"%s\"; }\n",
		   bb->name);
	  fprintf (fout, "node(\"%s\") { ", str_a);
	  if (strcmp (bb->name, "ENTRY") == 0
	      || strcmp (bb->name, "EXIT") == 0)
	    {
	      str_b = bb->name;
	    }
	  else
	    {
	      str_b = concat ("bb ", bb->name, NULL);
	    }

	  /* bb node */

	  if (strcmp (bb->name, "ENTRY") == 0
	      || strcmp (bb->name, "EXIT") == 0)
	    str_a = bb->name;
	  else
	    str_a = concat ("<bb ", bb->name, ">:", NULL);

	  if (bb->text == NULL)
	    {
	      str_b = str_a;
	    }
	  else
	    {
	      str_b = concat (str_a, "\n", bb->text, NULL);
	    }

	  fprintf (fout, "label=\"%s\"; }\n", str_b);

	  /* end of subgraph */
	  fprintf (fout, "}\n");
	}

      for (e = cfg->edge; e != NULL; e = e->next)
	{
	  /* edge */
	  str_a = concat (current_function->name, ".", e->source->name, NULL);
	  str_b = concat (current_function->name, ".", e->target->name, NULL);
	  fprintf (fout, "edge(\"%s\",\"%s\")", str_a, str_b);

	  if (e->type == RETREATING_EDGE)
	    {
	      fprintf (fout, " { style=\"dashed\"; }\n");
	    }
	  else
	    {
	      fprintf (fout, ";\n");
	    }

	}
      fprintf (fout, "}\n");
    }
  fprintf (fout, "}\n");

  return;
}
